home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UCommandHandler.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  10.4 KB  |  361 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UCommandHandler.cp 
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UCOMMANDHANDLER__
  7. #include "UCommandHandler.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UCLIPBOARDMGR__
  13. #include "UClipboardMgr.h"
  14. #endif
  15.  
  16. #ifndef __UCOREERRORMGR__
  17. #include "UCoreErrorMgr.h"
  18. #endif
  19.  
  20. #ifndef __UCOREGLOBALS__
  21. #include "UCoreGlobals.h"
  22. #endif
  23.  
  24. #ifndef __UDEBUG__
  25. #include "UDebug.h"
  26. #endif
  27.  
  28. #ifndef __UDISPATCHER__
  29. #include "UDispatcher.h"
  30. #endif
  31.  
  32. //    #ifndef __UERRORMGR__
  33. //    #include "UErrorMgr.h"
  34. //    #endif
  35.  
  36. #ifndef __UMACAPPGLOBALS__
  37. #include "UMacAppGlobals.h"
  38. #endif
  39.  
  40. //    #ifndef __UMACAPPUTILITIES__
  41. //    #include "UMacAppUtilities.h"
  42. //    #endif
  43.  
  44. #ifndef __UMEMORY__
  45. #include "UMemory.h"
  46. #endif
  47.  
  48. #ifndef __UMENUMGR__
  49. #include "UMenuMgr.h"
  50. #endif
  51.  
  52. #ifndef __USCRIPTING__
  53. #include "UScripting.h"
  54. #endif
  55.  
  56. #ifndef __USEGMENTS__
  57. #include "USegments.h"
  58. #endif
  59.  
  60. #ifndef __UUNDO__
  61. #include "UUndo.h"
  62. #endif
  63.  
  64. // ANSI
  65.  
  66. #ifndef __STDIO__
  67. #include <stdio.h>
  68. #endif
  69.  
  70. unsigned long TCommandHandler::fgTransactionIDCount;
  71.  
  72. //========================================================================================
  73. // CLASS TCommandHandler
  74. //========================================================================================
  75. #undef Inherited
  76. #define Inherited TEventHandler
  77.  
  78. #pragma segment MAEvtHandlerNonRes
  79. MA_DEFINE_CLASS_M1(TCommandHandler, Inherited);
  80.  
  81. //----------------------------------------------------------------------------------------
  82. // TCommandHandler constructor
  83. //----------------------------------------------------------------------------------------
  84. #pragma segment MAEvtHandlerRes
  85.  
  86. TCommandHandler::TCommandHandler() :
  87.     fPendingActionID(0)
  88. {
  89. }
  90.  
  91. //----------------------------------------------------------------------------------------
  92. // TCommandHandler::ICommandHandler:
  93. //----------------------------------------------------------------------------------------
  94. #pragma segment MAEvtHandlerRes
  95.  
  96. void TCommandHandler::ICommandHandler(TEventHandler* itsNextHandler)
  97. {
  98.     IEventHandler(itsNextHandler);
  99. }
  100.  
  101. //----------------------------------------------------------------------------------------
  102. // TCommandHandler::Clone: 
  103. //----------------------------------------------------------------------------------------
  104.  
  105. //----------------------------------------------------------------------------------------
  106. // TCommandHandler::Free:
  107. //----------------------------------------------------------------------------------------
  108. #pragma segment MAEvtHandlerRes
  109.  
  110. TCommandHandler::~TCommandHandler()
  111. {
  112.     //    fLastCommand = CommitACommand(fLastCommand);    // commit fLastCommand
  113.     //    fLastCommand = (TCommand*)FreeIfObject(fLastCommand);    // make sure it gets freed
  114.     
  115.     // ••• Need to check if we are in the undo history •••
  116.     
  117. }
  118.  
  119. //----------------------------------------------------------------------------------------
  120. // TCommandHandler::DoMenuCommand:
  121. //----------------------------------------------------------------------------------------
  122.  
  123. //----------------------------------------------------------------------------------------
  124. // TCommandHandler::HandleSetupMenus: Overridden to Adjust the Undo menu. This cannot be
  125. // done in an override of DoSetupMenus because TWindow::DoSetupMenus does not call the
  126. // Inherited method if the window is in a modal state.
  127. //----------------------------------------------------------------------------------------
  128.  
  129. //----------------------------------------------------------------------------------------
  130. // TCommandHandler::SetupUndoMenu:
  131. //----------------------------------------------------------------------------------------
  132.  
  133. //----------------------------------------------------------------------------------------
  134. // TCommandHandler::GetContext:
  135. //----------------------------------------------------------------------------------------
  136. #pragma segment MAEvtHandlerRes
  137.  
  138. TCommandHandler* TCommandHandler::GetContext(CommandNumber /* aCommandNumber */)
  139. {
  140.     return this;
  141. }
  142.  
  143. //----------------------------------------------------------------------------------------
  144. // TCommandHandler::PerformCommand:
  145. //----------------------------------------------------------------------------------------
  146. #pragma segment MAEvtHandlerRes
  147.  
  148. void TCommandHandler::PerformCommand(TCommand* command)
  149. {
  150.     //    MAVolatileInit(TCommand*, primaryCommand, command);
  151.     //    MAVolatileInit(TCommand*, linkedCommand, command->fLinkedCommand);
  152.  
  153.     //    Boolean cmdFreed = FALSE;    // can't be volatile because 
  154.     //    Boolean linkedCmdFreed = FALSE;        // they are passed by reference
  155.  
  156. #if qDebug
  157.     if (!command)
  158.     {
  159.         ProgramBreak("NULL passed to TCommandHandler::PerformCommand");
  160.         return;
  161.     }
  162.     else if (!IsObject(command))
  163.     {
  164.         // since it's possible to have passed in a freed undoable 
  165.         // command allocated in a global variable (due to pilot error)
  166.         VerboseIsObject(command);
  167.         ProgramBreak("###bogus object passed to TCommandHandler::DoPerformCommand");
  168.         return;
  169.     }
  170. #endif
  171.     
  172. #if qDebugMsg
  173.     if (gIntenseDebugging)
  174.         fprintf(stderr, "The Command to perform: %s\n", command->GetClassName());
  175. #endif
  176.  
  177.     //Boolean wasRecurring = command->IsRecurring();
  178.     //MAVolatileInit(TCommand*, volatileCommand, command);        
  179.  
  180.     if (command->fUseAppleEvent && PerformCommandAppleEvent(command))
  181.     {
  182.         // The command has been successfully converted to an Apple Event
  183.         // and performed as an Apple Event. We don't need it any more. 
  184.         //CommitACommand(command);
  185.         command->Completed();
  186.         if (command->ShouldFreeOnCompletion())
  187.             command = (TCommand*) FreeIfObject(command);
  188.         //cmdFreed = TRUE;
  189.         return;
  190.     }
  191.  
  192.     MAVolatileInit(TCommand*, volatileCommand, command);        
  193.     FailInfo fi;
  194.     Try(fi)
  195.     {
  196. #if qSegments
  197.         // Unload segs except in nested event handling
  198.         if ((gDispatcher->fEventLevel == 1)
  199.             && (volatileCommand->NeedsToUnloadAllSegments() || MemSpaceIsLow())
  200.             && (TOSADispatcher::fgDispatcher == NULL
  201.                 || TOSADispatcher::fgDispatcher->GetDispatchLevel() == 0))
  202.             UnloadAllSegments();
  203. #endif
  204.  
  205.         volatileCommand->DoIt();
  206.         volatileCommand->fCommandDone = TRUE;
  207.         fi.Success();
  208.     }
  209.     else // Recover
  210.     {
  211.         if (volatileCommand)
  212.         {
  213.             volatileCommand->SetValidationError(fi.error);
  214.             
  215.             // Save the ID because the command is going away. 
  216.             CommandNumber aCommandNumber = volatileCommand->fIdentifier;
  217.             
  218.             // Abort the current transaction in the undo handler. 
  219.             // This will free the command. 
  220.             TUndoHandler::fgUndoHandler->Abort();
  221.             
  222.             FailNewMessage(fi.error, fi.message, BuildMessage((short)aCommandNumber, messageCommandError));
  223.         }
  224.         fi.ReSignal();
  225.     }
  226.  
  227.     if (command)
  228.     {
  229.         // This is done after DoIt, so DoIt can change the fCausesChange flag. 
  230.         command->DoNotification();
  231.         
  232.         // Try to remove the command in case it is no longer recurring.
  233.         gDispatcher->RemoveEvent(command);
  234.         
  235.         // Either set up for undo, or get rid of it
  236.         if (command->CanBeUndone())
  237.             command->SetupDependencies();
  238.         else
  239.         {
  240.             command->Completed();
  241.             if (command->ShouldFreeOnCompletion())
  242.                 command = (TCommand*) FreeIfObject(command);
  243.         }
  244.     }
  245. }
  246.  
  247. //----------------------------------------------------------------------------------------
  248. // TCommandHandler::DoPerformCommand:
  249. //----------------------------------------------------------------------------------------
  250.  
  251. //----------------------------------------------------------------------------------------
  252. // TCommandHandler::PerformCommandAppleEvent:
  253. //----------------------------------------------------------------------------------------
  254. #pragma segment MAApplicationRes
  255.  
  256. Boolean    TCommandHandler::PerformCommandAppleEvent(TCommand* command)
  257. {
  258.     MAVolatileInit(TAppleEvent*, sendEvent, NULL);
  259.     MAVolatileInit(OSErr, dispatchError, noErr);
  260.     MAVolatileInit(long, processError, 0L);
  261.     
  262.     TAppleEvent    *resultEvent = NULL;
  263.     
  264.     FailInfo fi;
  265.     Try(fi)
  266.     {
  267.         sendEvent = command->MakeAppleEvent();
  268.         if (sendEvent)
  269.         {
  270. #if qDebug
  271.             Assertion(sendEvent->GetSendingMode() != kAEQueueReply,
  272.                       "Command-based apple events must be sent synchronously");
  273. #endif
  274.             if (!fgTransactionIDCount)
  275.                 fgTransactionIDCount = 1;
  276.                 
  277.             long transactionID = fgTransactionIDCount++;
  278.             
  279.             sendEvent->SetTransactionID(transactionID);
  280.             fPendingActionID = transactionID;
  281.             dispatchError = sendEvent->SendEvent(resultEvent);
  282.         }
  283.         fi.Success();
  284.     }
  285.     else    // Recover
  286.     {
  287.         dispatchError = fi.error;
  288.     }
  289.     
  290.     if ((dispatchError == noErr) && (resultEvent != NULL))
  291.     {
  292.         fi.Reset();
  293.         Try(fi)
  294.         {
  295.             if (resultEvent->HasParameter(keyErrorNumber))
  296.                 processError = resultEvent->ReadLong(keyErrorNumber);
  297.             fi.Success();
  298.         }
  299.         else    // Recover
  300.         {
  301.             // ignore the error
  302.         }
  303.     }
  304.     
  305.     FreeIfObject(sendEvent);
  306.     FreeIfObject(resultEvent);
  307.     return (dispatchError == noErr && processError == 0L);
  308. }
  309.  
  310. //----------------------------------------------------------------------------------------
  311. // TCommandHandler::GetLastCommand:
  312. //----------------------------------------------------------------------------------------
  313. #pragma segment MAEvtHandlerRes
  314.  
  315. TCommand* TCommandHandler::GetLastCommand()
  316. {
  317.     // ••• We could look for commands relating to us in the undo history •••
  318.     // ••• Maybe we don't have to •••
  319.     
  320.     return NULL;    // fLastCommand;
  321. }
  322.  
  323. //----------------------------------------------------------------------------------------
  324. // TCommandHandler::CommitLastCommand:
  325. //----------------------------------------------------------------------------------------
  326. #pragma segment MAApplicationRes
  327.  
  328. void TCommandHandler::CommitLastCommand()
  329. {
  330.     // Clear the entire action history. 
  331.     // It would be nice if we could clear only the actions that
  332.     // affect this command handler. Unfortunately, we don't know
  333.     // which actions depend on us, so we have to play safe. 
  334.     TUndoHandler::fgUndoHandler->ClearActionHistory(kDontRespectMarks);
  335. }
  336.  
  337. //----------------------------------------------------------------------------------------
  338. // TCommandHandler::PrepareForUndoRedo:
  339. //----------------------------------------------------------------------------------------
  340. #pragma segment MAApplicationRes
  341.  
  342. void TCommandHandler::PrepareForUndoRedo(TCommand* /*command*/)
  343. {
  344.     if (WantsToBeTarget())
  345.         BecomeTarget();
  346. }
  347.  
  348. //----------------------------------------------------------------------------------------
  349. // TCommandHandler::RevealUndoRedo:
  350. //----------------------------------------------------------------------------------------
  351. #pragma segment MAApplicationRes
  352.  
  353. void TCommandHandler::RevealUndoRedo(TCommand* /*command*/)
  354. {
  355. }
  356.  
  357. //----------------------------------------------------------------------------------------
  358. // End of UCommandHandler.cp
  359.  
  360. #pragma segment Inline
  361.